import './style/global.less'
import '@/utils/rem'
import 'virtual:svg-icons-register'

import { ExclamationCircleFilled } from '@ant-design/icons'
import { App as AppProvider, ConfigProvider, message } from 'antd'
import modal from 'antd/es/modal'
import arEG from 'antd/locale/ar_EG'
import enUS from 'antd/locale/en_US'
import cs from 'classnames'
import dayjs from 'dayjs'
import { useEffect, useMemo, useState } from 'react'
import ReactDOMClient from 'react-dom/client'
import { Provider } from 'react-redux'
import { HashRouter, Route, Switch } from 'react-router-dom'

import DashboardBg from '@/assets/dashboard-bg.png'
import DashboardBgx2 from '@/assets/dashboard-bgx2.png'
import DashboardBgx3 from '@/assets/dashboard-bgx3.png'
import DashboardBgx4 from '@/assets/dashboard-bgx4.png'
import eventBus from '@/utils/EventBus'

import { Check } from './api'
import { Violation } from './api/interface'
import { GlobalContext } from './context'
import PageLayout from './layout'
import locale from './locale'
import { Updater } from './network'
import store from './store'
import styles from './style/layout.module.less'
import { getAllData, updateCreate } from './syncData'
import changeTheme from './utils/changeTheme'
import { get, getJson, set } from './utils/storage'
import useStorage from './utils/useStorage'

function Index() {
  const image1x = new Image()
  image1x.src = DashboardBg

  const image2x = new Image()
  image2x.src = DashboardBgx2

  const image3x = new Image()
  image3x.src = DashboardBgx3

  const image4x = new Image()
  image4x.src = DashboardBgx4

  // 设置语言
  const [lang, setLang] = useStorage('arco-lang', 'ar-EG')

  const [systemLanguage, setSystemLanguage] = useState('ar-EG')
  useMemo(() => {
    const systemLanguage = navigator.language
    console.log(systemLanguage)
    if (systemLanguage.includes('ar')) {
      setLang('ar-EG')
      setSystemLanguage('ar-EG')
      return
    }
    setLang('en-US')
    setSystemLanguage('en-US')
    return
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])
  //设置主题
  const [theme, setTheme] = useStorage('arco-theme', 'light')
  //设置语言方向
  const [rtl, setRtl] = useState(lang === 'ar-EG')

  const t = locale[systemLanguage]
  useEffect(() => {
    changeTheme(theme)
  }, [theme])

  useEffect(() => {
    dayjs.locale(lang === 'en-US' ? 'en' : 'ar')
    setRtl(lang === 'ar-EG')
  }, [lang])

  // contextValue：这里使用全局上下文（Context）
  const contextValue = {
    systemLanguage,
    setSystemLanguage,
    lang,
    setLang,
    theme,
    setTheme,
    rtl,
    setRtl,
  }
  let timer: string | number | NodeJS.Timeout
  const messageKey = 'updatable'
  let updater: any

  const networkSuccess = () => {
    const orgName = get('orgName')
    if (systemLanguage === 'ar-EG') {
      return 'متصل بشبكة ' + orgName
    } else {
      return `Connected to ${orgName} network`
    }
  }
  const networkError = () => {
    const orgName = get('orgName')
    if (systemLanguage === 'ar-EG') {
      return 'تم قطع شبكة ' + orgName
    } else {
      return `${orgName} ${orgName ? 'network' : 'Network'} disconnected`
    }
  }

  const initError = () => {
    const orgName = get('orgName')
    if (systemLanguage === 'ar-EG') {
      return `فشلت التهيئة. يرجى الاتصال بشبكة ${orgName} للمحاولة مرة أخرى.`
    } else {
      return `Initialization failed. Please connect to the ${orgName} network to try again.`
    }
  }

  //初始化
  const fectchData = async () => {
    console.log('初始化开始')
    eventBus.emit('APPLOG', `【信息】初始化开始`)
    message.open({
      key: messageKey,
      type: 'loading',
      content: t['asyncData.init'],
      duration: 0,
    })
    eventBus.emit('APPLOG', `【提示】初始化loading`)
    const serialNumber = await window.electron?.ipcRenderer.serialNumber()
    store.dispatch({
      type: 'update-token',
      payload: {
        token: serialNumber,
      },
    })

    console.log('did', serialNumber)
    eventBus.emit('APPLOG', `【写入】Did：serialNumber`)
    try {
      const { data } = await Check()
      set('token', data.device.token)
      store.dispatch({
        type: 'update-orgName',
        payload: {
          orgName: data.sysOrg.name,
        },
      })
      eventBus.emit('APPLOG', `【写入】orgName：${data.sysOrg.name}`)
      set('isDeviceError', false)
      eventBus.emit('APPLOG', `【写入】isDeviceError：false`)
      await getAllData()
      set('isCheck', true)
      eventBus.emit('APPLOG', `【写入】iisCheck：true`)
      message.open({
        key: messageKey,
        type: 'success',
        content: t['asyncData.init.success'],
        duration: 3,
      })
      eventBus.emit('APPLOG', `【提示】初始化成功`)
    } catch (e) {
      eventBus.emit('APPLOG', `【提示】初始化失败`)
      if (e.code == 'ECONNABORTED') {
        message.open({
          key: messageKey,
          type: 'error',
          content: initError(),
          duration: 3,
        })
        return
      }
      if (e.data?.code !== 7000 && e.data?.code !== 'ERR_CANCELED') {
        message.open({
          key: messageKey,
          type: 'error',
          content: initError(),
          duration: 3,
        })

        return
      }
      throw e
    }
  }

  // 开始数据同步，静默更新的
  const startSyncData = async () => {
    console.log('离线数据同步')
    eventBus.emit('APPLOG', '【信息】离线数据同步开始')
    const serialNumber = await window.electron?.ipcRenderer.serialNumber()
    store.dispatch({
      type: 'update-token',
      payload: {
        token: serialNumber,
      },
    })
    eventBus.emit('APPLOG', `【写入】did ${serialNumber}`)
    try {
      const { data } = await Check()
      set('token', data.device.token)
      store.dispatch({
        type: 'update-orgName',
        payload: {
          orgName: data.sysOrg.name,
        },
      })
      eventBus.emit('APPLOG', `【写入】token ${data.device.token}`)
      set('isDeviceError', false)
      eventBus.emit('APPLOG', `【写入】是否设备异常：false`)
      await getAllData()
      const violationList: Partial<Violation>[] = getJson('violationList') || []

      if (violationList.length > 0) {
        await updateCreate(t)
      }
    } catch (e) {
      eventBus.emit('APPLOG', `【信息】离线数据同步出错`)
      console.log(e)
    }
  }

  const startTimer = async () => {
    eventBus.emit('APPLOG', `【信息】开始定时任务`)
    //判断时初始化还是离线同步数据
    try {
      const networkStatus = get('networkStatus')
      if (!networkStatus) {
        eventBus.emit('APPLOG', `【信息】无网络`)
        throw new Error('No network')
      }
      const isCheck = get('isCheck')
      const isDeviceError = get('isDeviceError')
      console.log('是否初始化', !!isCheck)
      console.log('是否设备异常', !!isDeviceError)
      eventBus.emit('APPLOG', `【信息】是否初始化：${!!isCheck ? 'true' : 'false'}`)
      eventBus.emit('APPLOG', `【信息】是否设备异常：${!!isDeviceError ? 'true' : 'false'}`)
      // 已初始化开始定时任务
      if (!!isCheck) {
        eventBus.emit('APPLOG', `【信息】已初始化开始定时任务`)
        await startSyncData()
        return
      }
      //未初始化每次都要开始初始化
      eventBus.emit('APPLOG', `【信息】未初始化开始定时任务`)
      await fectchData()
    } finally {
      if (timer) {
        clearTimeout(timer)
      }
      timer = setTimeout(async () => {
        await startTimer()
      }, 10 * 60 * 1000)
    }
  }

  const onFsPermissions = async () => {
    const text = await window.electron?.ipcRenderer.onFs()
    console.log(text)
    eventBus.emit('APPLOG', `【信息】${text}`)
  }

  useEffect(() => {
    onFsPermissions()
    eventBus.emit('APPLOG', '【信息】开始监听网络')
    updater = new Updater({
      time: 5000, // 设置轮询时间间隔为5秒
      url: '/wajib/admin/test/check',
    })
    const handleUpdate = async (e) => {
      eventBus.emit('APPLOG', `【信息】网络变化：${e}`)
      store.dispatch({
        type: 'update-networkStatus',
        payload: {
          networkStatus: e,
        },
      })
      eventBus.emit('APPLOG', `【写入】网络状态`)
      message.open({
        key: 'update-networkStatus',
        type: e ? 'success' : 'error',
        content: e ? networkSuccess() : networkError(),
        duration: 3,
      })
      eventBus.emit('APPLOG', `【提示】网络状态提示`)
      //有网
      if (e) {
        eventBus.emit('APPLOG', `【信息】正常网络`)
        startTimer()
      } else {
        eventBus.emit('APPLOG', `【信息】无网络`)
        // 未联网时提示分为初始化和未初始化看两种
        const isCheck = get('isCheck')
        const isDeviceError = get('isDeviceError')
        console.log('是否初始化', !!isCheck)
        console.log('是否设备异常', !!isDeviceError)
        eventBus.emit('APPLOG', `【信息】是否初始化：${!!isCheck ? 'true' : 'false'}`)
        eventBus.emit('APPLOG', `【信息】是否设备异常：${!!isDeviceError ? 'true' : 'false'}`)
        if (!!isDeviceError) {
          message.open({
            key: messageKey,
            type: 'error',
            content: t['asyncData.device.error'],
            duration: 3,
          })
          eventBus.emit('APPLOG', `【提示】设备异常`)
          return
        }
        //未初始化
        if (!isCheck) {
          message.open({
            key: messageKey,
            type: 'error',
            content: initError(),
            duration: 3,
          })
          eventBus.emit('APPLOG', `【提示】未初始化`)
          return
        }
      }
    }
    // handleUpdate(true)
    updater.on('update', handleUpdate)

    return () => {
      updater.off('update', handleUpdate)
      if (timer) {
        clearTimeout(timer)
      }
    }
  }, [])

  useEffect(() => {
    /**
     * 获取报告数量
     */
    //监听离线报告变化
    window.electron?.ipcRenderer.onStoreChange((value, oldValue) => {
      const violationList: Partial<Violation>[] = value?.violationList
        ? JSON.parse(value?.violationList)
        : []
      const oldViolationList: Partial<Violation>[] = oldValue?.violationList
        ? JSON.parse(oldValue?.violationList)
        : []
      const length = violationList.length
      const oldLength = oldViolationList.length
      console.log('离线报告变化', oldLength, length)
      if (length !== 0 && length != oldLength) {
        store.dispatch({
          type: 'update-dashboardNum',
          payload: {
            dashboardNum: length,
          },
        })
        return
      }
      if (length == 0) {
        store.dispatch({
          type: 'update-dashboardNum',
          payload: {
            dashboardNum: length,
          },
        })
      }
    })
    //初始化获取报告数量
    const violationList: Partial<Violation>[] = getJson('violationList') || []
    const closeTime = get('closeTime')
    const length = violationList.length
    console.log('离线报告数', length)
    console.log('是否是同一天', !dayjs().isSame(closeTime, 'day'))
    //大于0且上次关闭时间和当前不是同一个时间
    if (length !== 0 && !dayjs().isSame(closeTime, 'day')) {
      store.dispatch({
        type: 'update-dashboardNum',
        payload: {
          dashboardNum: length,
        },
      })
      return
    }
    if (length == 0) {
      store.dispatch({
        type: 'update-dashboardNum',
        payload: {
          dashboardNum: length,
        },
      })
    }
  }, [])

  //退出监听
  useEffect(() => {
    window.electron?.ipcRenderer.close(() => {
      close()
    })
  }, [])

  // 软件退出弹窗提醒
  const close = async () => {
    modal.confirm({
      title: t['confirm.title'],
      icon: <ExclamationCircleFilled style={{ color: '#FF7D00' }} />,
      className: cs(styles['custom-modal'], lang === 'en-US' ? '' : styles['custom-modal-rtl']),
      closable: true,
      content: t['confirm.content'],
      okText: t['confirm.button.yes'],
      okButtonProps: { danger: true },
      cancelText: t['confirm.button.no'],
      keyboard: false,
      centered: true,
      onOk() {
        window.electron?.ipcRenderer.confirmClose()
      },
    })
  }

  return (
    <HashRouter>
      {/* locale通过 ConfigProvider 组件实现国际化。 */}
      {/* componentConfig设置全局组件配置 */}
      <ConfigProvider
        locale={lang === 'en-US' ? enUS : arEG}
        direction={lang === 'en-US' ? 'ltr' : 'rtl'}
        theme={{ token: { colorPrimary: '#44C5E4' } }}
      >
        <AppProvider>
          {/* <Provider store={store}>这里通过Redux的Provider组件将store传递给React应用，使应用的组件都能够访问到Redux的状态。 */}
          <Provider store={store}>
            {/* <GlobalContext.Provider value={contextValue}>：这里使用全局上下文（Context）的Provider组件，将一个名为contextValue的值传递给React应用中的组件，使得这些组件都能够访问到这个值。 */}
            <GlobalContext.Provider value={contextValue}>
              {/* <Switch>：这个组件表示一组Route组件，用于在路由匹配时只渲染第一个匹配到的Rout */}
              <Switch>
                <Route path="/" component={PageLayout} />
              </Switch>
            </GlobalContext.Provider>
          </Provider>
        </AppProvider>
      </ConfigProvider>
    </HashRouter>
  )
}

let root = null
const container = document.getElementById('root')
if (!root || !root._internalRoot) {
  root = ReactDOMClient.createRoot(container)
}
root.render(<Index />)
